/**
 * 
 */
package com.nari.interfaces.decipher.gprs.protocolcodec;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.charset.Charset;
import java.util.Date;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;

import com.nari.interfaces.decipher.gprs.FrameEntitySeal;
import com.nari.interfaces.decipher.gprs.vo.ClientHost;
import com.nari.interfaces.decipher.gprs.vo.UploadMeterDataSeal;
import com.nari.platform.date.CalendarUtils;
import com.nari.platform.utils.NumberSystemConversion;

/**
 * 基于帧协议的数据解码器
 * 说明：累积性的协议解码器，可以将读取的协议数据累计到内部的IoBuffer缓冲区，
 * 直到接收到完整的数据包，再进行协议数据解码。
 * 协议解码，具体的拆包交由子类的doDecode()方法完成。
 * @author Xiaopeng
 * @date 2013-10-31
 */
public class FrameProtocolDecoder extends CumulativeProtocolDecoder {
	private final Charset charset;

	/**
	 * 帧协议解码器构造实例
	 * @param charset
	 */
	public FrameProtocolDecoder(Charset charset) {
		this.charset = charset;
	}
	
	/**
	 * 消息解码
	 * 1、每次一个完整的信息被解码后，需要将它写给ProtocolDecoderOutput，
	 * 这个信息将会顺序穿过所有的过滤器，并最终到达你的IoHandler.messageReceived方法；
	 * 2、如果没有足够的有效信息来进行解码工作，它将会返回false
	 * @param session
	 * @param bufferIn
	 * @param decoderOutput
	 * @return
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2013-10-31
	 */
	protected synchronized boolean doDecode(IoSession session, IoBuffer bufferIn,
			ProtocolDecoderOutput decoderOutput) throws Exception {
		SocketAddress socketAddress = session.getRemoteAddress();
		InetSocketAddress inetAddress = (InetSocketAddress) socketAddress;
		String connectIP = inetAddress.getAddress().getHostAddress();
		int port = inetAddress.getPort();
		ClientHost clientHost = ClientHost.getInstance(connectIP, port);
		//消息字符解码
//		CharsetDecoder charsetDecoder = this.charset.newDecoder();
		//读取数据帧
		byte[] receivedBytes = new byte[bufferIn.limit()];
		bufferIn.get(receivedBytes);
		String receivedData = NumberSystemConversion.formatByteArray2HexString(receivedBytes, " ");
		System.out.println("######Received Decoder "+clientHost+"["+CalendarUtils.parseDateTimeToString(new Date())+"]######");
		System.out.println(receivedData);
		System.out.println("##############################################################");
		receivedData = receivedData.toUpperCase();
		//若数据成功接收，则要求发送下一帧数据；否则要求重发(要求下次的帧序号为当前帧)
		UploadMeterDataSeal meterDataSeal = new UploadMeterDataSeal();
		if (receivedData.startsWith("FE 68") && receivedData.endsWith("16")) {
			//解码客户端数据帧
			meterDataSeal = FrameEntitySeal.decodeClientFrame(receivedData);
			//依据客户端数据帧，计算下一帧的帧序号
			meterDataSeal.setRequestFrameIndex(meterDataSeal.getCurrFrameIndex() + 1);
		} 
		//解析数据回传到业务处理IoHandler，便于记录状态，支持断点续传功能
		decoderOutput.write(meterDataSeal);
		return true;
	}
	
	/**
	 * 手动释放会话解码所申请的资源
	 * @param session
	 * @throws Exception
	 * @author Xiaopeng
	 * @date 2013-11-5
	 */
	public void dispose(IoSession session) throws Exception {
		super.dispose(session);
	}
	
}
